package com.sos.core.game
{
	import com.sos.core.DataObject;
	import com.sos.core.Position;

	public class GameTurn extends DataObject
	{
		
		// -------------------------------------------------------------------------------
		// CONSTANTS
		// -------------------------------------------------------------------------------
		
		// JSON property names
		public static const		JSON_PROPERTY_INIT:String				= "init";
		public static const		JSON_PROPERTY_ACTION:String				= "action";
		public static const		JSON_PROPERTY_ACTION_TARGET:String		= "actionTarget";
		public static const		JSON_PROPERTY_ACTION_TARGETID:String	= "actionTargetId";
		public static const		JSON_PROPERTY_PLAYERS:String			= "players";
		public static const		JSON_PROPERTY_PLAYER_ABILITIES:String	= "playerAbilities";
		public static const		JSON_PROPERTY_PLAYER_ATT:String			= "att";
		public static const		JSON_PROPERTY_PLAYER_DEF:String			= "def";
		public static const		JSON_PROPERTY_CARDS:String				= "cards";
		public static const		JSON_PROPERTY_SOLVE_MAIN:String			= "solveMain";
		public static const		JSON_PROPERTY_SOLVE_SCORE:String		= "solveScore";
		public static const		JSON_PROPERTY_LOG_ROWS:String			= "logRows";
		public static const		JSON_PROPERTY_OUTPUT:String				= "unexpectedOutput";
		
		// Default values
		protected static const      DEFAULT_ACTION:GameAction				= GameAction.PASS;
		protected static const      DEFAULT_ACTION_TARGET:Position			= Position.MIDFIELD;
		protected static const      DEFAULT_ATTACKER_CARD_ID:int			= DataObject.INVALID_ID;
		protected static const      DEFAULT_DEFENDER_CARD_ID:int			= DataObject.INVALID_ID;
		
		// -------------------------------------------------------------------------------
		// FIELDS
		// -------------------------------------------------------------------------------
		
		private var _playerSide:GameSide;		// permette di sapere il ruolo
		private var _playerRole:GameRole;		// permette di sapere il ruolo
		private var _action:GameAction;
		private var _target:Position;
		private var _targetCardId:uint;
		private var _attackerCardId:uint;
		private var _defenderCardId:uint;
		private var _procHolder:GameProcHolder;
		private var _casts:Vector.<GameCast>;
		private var _solve:GameTurnSolve;	// LT_TODO: mappare la classe per solve
		private var _solveScore:GameTurnSolveScore;			// LT_TODO: mappare la classe per solve
		private var _output:String;
		private var _logRows:Vector.<GameLogRow>;
		
		// -------------------------------------------------------------------------------
		// CONSTRUCTORS
		// -------------------------------------------------------------------------------
		
		public function GameTurn(data:Object = null, playerSide:GameSide = null, playerRole:GameRole = null)
		{
			super();
			// Init objects
			_casts = new Vector.<GameCast>;
			// Ruolo e "lato" del giocatore
			if (playerSide != null) _playerSide = playerSide;
			if (playerRole != null) _playerRole = playerRole;
			// Init objects
			_solve 		= new GameTurnSolve();
			_solveScore = new GameTurnSolveScore();
			_logRows	= new Vector.<GameLogRow>;
			// Clear
			clear();
			// If data is provided, initializes the turn
			if (data != null) load(data);
		}
		
		// -------------------------------------------------------------------------------
		// PROPERTIES
		// -------------------------------------------------------------------------------	
		
		public function get action():GameAction
		{
			return _action;
		}
		
		public function set action(value:GameAction):void
		{
			_action = value;
		}
		
		public function get target():Position
		{
			return _target;
		}
		
		public function set target(value:Position):void
		{
			_target = value;
		}
		
		public function get attackerCardId():uint
		{
			return _attackerCardId;
		}
		
		public function set attackerCardId(value:uint):void
		{
			_attackerCardId = value;
		}
		
		public function get defenderCardId():uint
		{
			return _defenderCardId;
		}
		
		public function set defenderCardId(value:uint):void
		{
			_defenderCardId = value;
		}
		
		public function get casts():Vector.<GameCast>
		{
			return _casts;
		}
		
		public function get playerWins():Boolean
		{
			return hasPlayerData ? _solve.winner == _playerRole : false;
		}
		
		public function get playerRoll():uint
		{
			return hasPlayerData ? isPlayerAttacking ? _solve.attackerRoll : _solve.defenderRoll : 0;
		}
		
		public function get playerScore():uint
		{
			return hasPlayerData ? isPlayerAttacking ? _solve.attackerScore : _solve.defenderScore : 0;
		}
		
		public function get opponentRoll():uint
		{
			return hasPlayerData ? isPlayerAttacking ? _solve.defenderRoll : _solve.attackerRoll : 0;
		}
		
		public function get opponentScore():uint
		{
			return hasPlayerData ? isPlayerAttacking ? _solve.defenderScore : _solve.attackerScore : 0;
		}
		
		public function get playerSide():GameSide
		{
			return _playerSide;
		}
		
		public function get playerRole():GameRole
		{
			return _playerRole;
		}
		
		public function get solve():GameTurnSolve
		{
			return _solve;
		}
		
		public function set solve(value:GameTurnSolve):void
		{
			_solve = value;
		}
		
		public function get solveScore():GameTurnSolveScore
		{
			return _solveScore;
		}
		
		public function set solveScore(value:GameTurnSolveScore):void
		{
			_solveScore = value;
		}
		
		public function get isPlayerAttacking():Boolean
		{
			return _playerRole == GameRole.ATTACK;
		}
		
		public function get hasPlayerData():Boolean
		{
			return _playerRole != null && _playerSide != null;
		}
		
		public function get targetCardId():uint 
		{
			return _targetCardId;
		}
		
		public function set targetCardId(value:uint):void 
		{
			_targetCardId = value;
		}
		
		public function get procHolder():GameProcHolder 
		{
			return _procHolder;
		}
		
		public function set procHolder(value:GameProcHolder):void 
		{
			_procHolder = value;
		}
		
		public function get logRows():Vector.<GameLogRow> 
		{
			return _logRows;
		}
		
		public function set logRows(value:Vector.<GameLogRow>):void 
		{
			_logRows = value;
		}
		
		public function get output():String 
		{
			return _output;
		}
		
		public function set output(value:String):void 
		{
			_output = value;
		}
		
		// -------------------------------------------------------------------------------
		// PRIVATE METHODS
		// -------------------------------------------------------------------------------
		
		// DataObject implementation
		
		override protected function validate(data:Object):void
		{
			// Base properties
			if (!data.hasOwnProperty(JSON_PROPERTY_INIT)) 		throwLoadMissingPropError(JSON_PROPERTY_INIT);
			// POSSONO ANCHE NON ESSERE GIOCATE CARTE IMBECILLE! if (!data.hasOwnProperty(JSON_PROPERTY_CARDS))		throwLoadMissingPropError(JSON_PROPERTY_CARDS);
			if (!data.hasOwnProperty(JSON_PROPERTY_SOLVE_MAIN))	throwLoadMissingPropError(JSON_PROPERTY_SOLVE_MAIN);
			
			// Init struct
			if (!data[JSON_PROPERTY_INIT].hasOwnProperty(JSON_PROPERTY_ACTION)) 		
				throwLoadMissingPathError(JSON_PROPERTY_INIT, JSON_PROPERTY_ACTION);
			if (!data[JSON_PROPERTY_INIT].hasOwnProperty(JSON_PROPERTY_ACTION_TARGET))	
				throwLoadMissingPathError(JSON_PROPERTY_INIT, JSON_PROPERTY_ACTION_TARGET);
			if (!data[JSON_PROPERTY_INIT].hasOwnProperty(JSON_PROPERTY_PLAYERS))		
				throwLoadMissingPathError(JSON_PROPERTY_INIT, JSON_PROPERTY_PLAYERS);
			if (!data[JSON_PROPERTY_INIT][JSON_PROPERTY_PLAYERS].hasOwnProperty(JSON_PROPERTY_PLAYER_ATT))
				throwLoadMissingPathError(JSON_PROPERTY_PLAYERS, JSON_PROPERTY_PLAYER_ATT);
			if (!data[JSON_PROPERTY_INIT][JSON_PROPERTY_PLAYERS].hasOwnProperty(JSON_PROPERTY_PLAYER_DEF))
				throwLoadMissingPathError(JSON_PROPERTY_PLAYERS, JSON_PROPERTY_PLAYER_DEF);
			
		}
		
		override protected function fill(data:Object):void
		{
			// raw objects
			var raw_init:Object = data[JSON_PROPERTY_INIT];
			var raw_init_players:Object = data[JSON_PROPERTY_INIT][JSON_PROPERTY_PLAYERS];
			// Turn data
			_action = GameAction.getByName(raw_init[JSON_PROPERTY_ACTION]);
			_target = Position.getBySign(raw_init[JSON_PROPERTY_ACTION_TARGET]);
			_attackerCardId = uint(raw_init_players[JSON_PROPERTY_PLAYER_ATT]);
			_defenderCardId = uint(raw_init_players[JSON_PROPERTY_PLAYER_DEF]);
			_targetCardId = uint(raw_init[JSON_PROPERTY_ACTION_TARGETID]);
			
			if (data.hasOwnProperty(JSON_PROPERTY_OUTPUT))
				_output = data[JSON_PROPERTY_OUTPUT];
			//Player abilities
			if (data.hasOwnProperty(JSON_PROPERTY_PLAYER_ABILITIES))
			{
				_procHolder = new GameProcHolder(data[JSON_PROPERTY_PLAYER_ABILITIES]);
			}
			
			// LogRows
			var logRows:Vector.<GameLogRow> = new Vector.<GameLogRow>();
			// Verifico se ho i dati delle carte giocate
			if (data.hasOwnProperty(JSON_PROPERTY_LOG_ROWS))
			{
				var raw_logRows:Array = data[JSON_PROPERTY_LOG_ROWS];
				
				// Loop over casts raw array
				for (var i:int = 0; i < raw_logRows.length; i++)
				{
					logRows.push(new GameLogRow(raw_logRows[i]));
				}
			}
			// Clear current and add the new list
			_logRows.splice(0, _logRows.length);
			for (var j:int = 0; j < logRows.length; j++)
			{
				_logRows.push(logRows[j]);
			}
			
			// Casts
			var casts:Vector.<GameCast> = new Vector.<GameCast>();
			// Verifico se ho i dati delle carte giocate
			if (data.hasOwnProperty(JSON_PROPERTY_CARDS))
			{
				var raw_casts:Array = data[JSON_PROPERTY_CARDS];
				
				// Loop over casts raw array
				for (var c:int = 0; c < raw_casts.length; c++)
				{
					casts.push(new GameCast(raw_casts[c]));
				}
			}
			// Clear current and add the new list
			_casts.splice(0, _casts.length);
			for (var p:int = 0; p < casts.length; p++)
			{
				_casts.push(casts[p]);
			}
			// Solve main data
			// LT_TODO: rimosso _solveMain = data[JSON_PROPERTY_SOLVE_MAIN];
			_solve.load(data[JSON_PROPERTY_SOLVE_MAIN]);
			// Solve score data
			if (data[JSON_PROPERTY_SOLVE_SCORE])
			{
				_solveScore = new GameTurnSolveScore();
				_solveScore.load(data[JSON_PROPERTY_SOLVE_SCORE]);
			}
		}

		// -------------------------------------------------------------------------------
		// PUBLIC METHODS
		// -------------------------------------------------------------------------------
		
		override public function clear():void
		{
			// Clear data
			_action 		= DEFAULT_ACTION;
			_target 		= DEFAULT_ACTION_TARGET;
			_attackerCardId	= DEFAULT_ATTACKER_CARD_ID;
			_defenderCardId	= DEFAULT_DEFENDER_CARD_ID;
			_output			= "";
			// Clear objects
			_solve.clear();
			_solveScore.clear();
			// Clear objects
			_casts.splice(0, _casts.length);
			_logRows.splice(0, _logRows.length);
			
		}

		
	}
}